﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DynamicComboBox
{
    public partial class DynamicComboBox : ComboBox
    {
        private string[] scoreStrings = { "--------", "Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma" };
        private Dictionary<string, uint> scoreMap;
        private string previousScore;

        public string PreviousScore
        {
            get { return previousScore; }
            set { previousScore = value; }
        }

        public DynamicComboBox()
        {
            InitializeComponent();
            ResetComboBox();
        }

        public void ResetComboBox()
        {
            //this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
            //this.DrawItem += new DrawItemEventHandler(DrawBox);

            Items.Clear();

            scoreMap = new Dictionary<string, uint>();
            previousScore = scoreStrings[0];

            for (uint score = 0; score < 7; ++score)
            {
                scoreMap[scoreStrings[score]] = score;
            }
            this.Items.AddRange(scoreStrings);
            this.SelectedIndex = 0;
        }
        private void DrawBox(object sender, System.Windows.Forms.DrawItemEventArgs e)
        {
            // This function could be used to fulfil the requirements of the OTHER OPTION, 
            // listed in the function following this one.
            e.DrawBackground();

            for (int ability = 0; ability < this.Items.Count; ++ability)
            {
                e.Graphics.DrawString((string)this.Items[ability],  e.Font, Brushes.Black, e.Bounds, StringFormat.GenericDefault);
            }
        }
        public void ProcessNewAbilityScoreChoice(DynamicComboBox sender)
        {
            // Remove the desired string from the current collection,
            // unless it's the default string and it's the one we've currently selected
            // Make sure to maintain desired order

            // if the sender is myself, don't do anything
            // also, don't do anything if the ability to process and the previously selected ability are the same
            string abilityToProcess = sender.Items[sender.SelectedIndex].ToString();
            string sendersPreviousScore = sender.PreviousScore;
            if (this.Equals(sender) || abilityToProcess.Equals(sendersPreviousScore))
            {
                return;
            }

            // Otherwise, we need to process the sender's newly selected string through my list
            // if the ability string to process IS NOT the default, we want to remove it from my collection
            if (!abilityToProcess.Equals(scoreStrings[0]))
            {
                this.Items.Remove(abilityToProcess);
            }

            // If the sender had a valid previously selected string, we want to add it back
            // to my own list and arrange it to maintain order
            if (!sendersPreviousScore.Equals(scoreStrings[0]))
            {
                this.Items.Add(sendersPreviousScore);
                ArrangeListInOrder();
            }

            // THE OTHER OPTION
            // There's also the opportunity for some better usability here
            // Instead of removing the ability from the other boxes, leave it there
            // but color it a "Used" color, thus still allowing for the user to make quicker changes
            // to the scores they want to assign
            // The functionality should be as follows:
            //      1. When the user selects an ability score, highlight it red in all other boxes
            //      2. If a red ability score is selected, do the following:
            //              a. deselect it in the previous box (set the current to the default string)
            //              b. maintain the "used" status in the other idle boxes
            //              c. assign the ability in the current box
        }

        private void ArrangeListInOrder()
        {
            // Make sure to save the current string we're on so we don't forget about it!
            string currentAbility = this.Items[this.SelectedIndex].ToString();

            // Make a list of indices that correspond to the abilities listed in the box
            List<uint> indices = new List<uint>();
            foreach (string ability in this.Items.OfType<string>())
            {
                indices.Add(scoreMap[ability]);
            }

            // Sort the new list, so its contents are in ascending order
            indices.Sort();

            // Clear this box's current list, 
            // then insert the abilities in the order
            // determined by the list of indices
            this.Items.Clear();
            foreach (uint index in indices)
            {
                this.Items.Add(scoreStrings[index]);
            }

            // If there was a currently selected index, reset it now
            for (int index = 0; index < this.Items.Count; ++index)
            {
                if (currentAbility == this.Items[index].ToString())
                {
                    this.SelectedIndex = index;
                }
            }
        }
    }
}
